home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / c / time / RCS / ctime.c,v < prev    next >
Text File  |  1988-07-29  |  9KB  |  457 lines

  1. head     1.3;
  2. access   ;
  3. symbols  ;
  4. locks    ; strict;
  5. comment  @ * @;
  6.  
  7.  
  8. 1.3
  9. date     88.07.29.17.10.10;  author ouster;  state Exp;
  10. branches ;
  11. next     1.2;
  12.  
  13. 1.2
  14. date     88.07.25.11.16.48;  author ouster;  state Exp;
  15. branches ;
  16. next     1.1;
  17.  
  18. 1.1
  19. date     88.07.02.14.54.36;  author ouster;  state Exp;
  20. branches ;
  21. next     ;
  22.  
  23.  
  24. desc
  25. @@
  26.  
  27.  
  28. 1.3
  29. log
  30. @Lint.
  31. @
  32. text
  33. @/*
  34.  * Copyright (c) 1987 Regents of the University of California.
  35.  * All rights reserved.
  36.  *
  37.  * Redistribution and use in source and binary forms are permitted
  38.  * provided that this notice is preserved and that due credit is given
  39.  * to the University of California at Berkeley. The name of the University
  40.  * may not be used to endorse or promote products derived from this
  41.  * software without specific written prior permission. This software
  42.  * is provided ``as is'' without express or implied warranty.
  43.  *
  44.  * This code was supplied by Arthur Olson, originally, and has been
  45.  * slightly modified at the University of California.
  46.  */
  47.  
  48. #if defined(LIBC_SCCS) && !defined(lint)
  49. static char sccsid[] = "@@(#)ctime.c    5.12 (Berkeley) 12/3/87";
  50. #endif /* LIBC_SCCS and not lint */
  51.  
  52. #include <stdio.h>
  53. #include <sys/param.h>
  54. #include <sys/time.h>
  55. #include <tzfile.h>
  56.  
  57. char *
  58. ctime(t)
  59. time_t *t;
  60. {
  61.     struct tm    *localtime();
  62.     char    *asctime();
  63.  
  64.     return(asctime(localtime(t)));
  65. }
  66.  
  67. /*
  68. ** A la X3J11
  69. */
  70.  
  71. char *
  72. asctime(timeptr)
  73. register struct tm *    timeptr;
  74. {
  75.     static char    wday_name[DAYS_PER_WEEK][3] = {
  76.         "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  77.     };
  78.     static char    mon_name[MONS_PER_YEAR][3] = {
  79.         "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  80.         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  81.     };
  82.     static char    result[26];
  83.  
  84.     (void) sprintf(result, "%.3s %.3s%3d %02d:%02d:%02d %d\n",
  85.         wday_name[timeptr->tm_wday],
  86.         mon_name[timeptr->tm_mon],
  87.         timeptr->tm_mday, timeptr->tm_hour,
  88.         timeptr->tm_min, timeptr->tm_sec,
  89.         TM_YEAR_BASE + timeptr->tm_year);
  90.     return result;
  91. }
  92.  
  93. #ifndef TRUE
  94. #define TRUE        1
  95. #define FALSE        0
  96. #endif /* !TRUE */
  97.  
  98. extern char *        getenv();
  99. extern char *        strcpy();
  100. extern char *        strcat();
  101. struct tm *        offtime();
  102.  
  103. struct ttinfo {                /* time type information */
  104.     long        tt_gmtoff;    /* GMT offset in seconds */
  105.     int        tt_isdst;    /* used to set tm_isdst */
  106.     int        tt_abbrind;    /* abbreviation list index */
  107. };
  108.  
  109. struct state {
  110.     int        timecnt;
  111.     int        typecnt;
  112.     int        charcnt;
  113.     time_t        ats[TZ_MAX_TIMES];
  114.     unsigned char    types[TZ_MAX_TIMES];
  115.     struct ttinfo    ttis[TZ_MAX_TYPES];
  116.     char        chars[TZ_MAX_CHARS + 1];
  117. };
  118.  
  119. static struct state    s;
  120.  
  121. static int        tz_is_set;
  122.  
  123. char *            tzname[2] = {
  124.     "GMT",
  125.     "GMT"
  126. };
  127.  
  128. #ifdef USG_COMPAT
  129. time_t            timezone = 0;
  130. int            daylight = 0;
  131. #endif /* USG_COMPAT */
  132.  
  133. static long
  134. detzcode(codep)
  135. char *    codep;
  136. {
  137.     register long    result;
  138.     register int    i;
  139.  
  140.     result = 0;
  141.     for (i = 0; i < 4; ++i)
  142.         result = (result << 8) | (codep[i] & 0xff);
  143.     return result;
  144. }
  145.  
  146. static
  147. tzload(name)
  148. register char *    name;
  149. {
  150.     register int    i;
  151.     register int    fid;
  152.  
  153.     if (name == 0 && (name = TZDEFAULT) == 0)
  154.         return -1;
  155.     {
  156.         register char *    p;
  157.         register int    doaccess;
  158.         char        fullname[MAXPATHLEN];
  159.  
  160.         doaccess = name[0] == '/';
  161.         if (!doaccess) {
  162.             if ((p = TZDIR) == 0)
  163.                 return -1;
  164.             if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
  165.                 return -1;
  166.             (void) strcpy(fullname, p);
  167.             (void) strcat(fullname, "/");
  168.             (void) strcat(fullname, name);
  169.             /*
  170.             ** Set doaccess if '.' (as in "../") shows up in name.
  171.             */
  172.             while (*name != '\0')
  173.                 if (*name++ == '.')
  174.                     doaccess = TRUE;
  175.             name = fullname;
  176.         }
  177.         if (doaccess && access(name, 4) != 0)
  178.             return -1;
  179.         if ((fid = open(name, 0, 0)) == -1)
  180.             return -1;
  181.     }
  182.     {
  183.         register char *            p;
  184.         register struct tzhead *    tzhp;
  185.         char                buf[sizeof s];
  186.  
  187.         i = read(fid, buf, sizeof buf);
  188.         if (close(fid) != 0 || i < sizeof *tzhp)
  189.             return -1;
  190.         tzhp = (struct tzhead *) buf;
  191.         s.timecnt = (int) detzcode(tzhp->tzh_timecnt);
  192.         s.typecnt = (int) detzcode(tzhp->tzh_typecnt);
  193.         s.charcnt = (int) detzcode(tzhp->tzh_charcnt);
  194.         if (s.timecnt > TZ_MAX_TIMES ||
  195.             s.typecnt == 0 ||
  196.             s.typecnt > TZ_MAX_TYPES ||
  197.             s.charcnt > TZ_MAX_CHARS)
  198.                 return -1;
  199.         if (i < sizeof *tzhp +
  200.             s.timecnt * (4 + sizeof (char)) +
  201.             s.typecnt * (4 + 2 * sizeof (char)) +
  202.             s.charcnt * sizeof (char))
  203.                 return -1;
  204.         p = buf + sizeof *tzhp;
  205.         for (i = 0; i < s.timecnt; ++i) {
  206.             s.ats[i] = detzcode(p);
  207.             p += 4;
  208.         }
  209.         for (i = 0; i < s.timecnt; ++i)
  210.             s.types[i] = (unsigned char) *p++;
  211.         for (i = 0; i < s.typecnt; ++i) {
  212.             register struct ttinfo *    ttisp;
  213.  
  214.             ttisp = &s.ttis[i];
  215.             ttisp->tt_gmtoff = detzcode(p);
  216.             p += 4;
  217.             ttisp->tt_isdst = (unsigned char) *p++;
  218.             ttisp->tt_abbrind = (unsigned char) *p++;
  219.         }
  220.         for (i = 0; i < s.charcnt; ++i)
  221.             s.chars[i] = *p++;
  222.         s.chars[i] = '\0';    /* ensure '\0' at end */
  223.     }
  224.     /*
  225.     ** Check that all the local time type indices are valid.
  226.     */
  227.     for (i = 0; i < s.timecnt; ++i)
  228.         if (s.types[i] >= s.typecnt)
  229.             return -1;
  230.     /*
  231.     ** Check that all abbreviation indices are valid.
  232.     */
  233.     for (i = 0; i < s.typecnt; ++i)
  234.         if (s.ttis[i].tt_abbrind >= s.charcnt)
  235.             return -1;
  236.     /*
  237.     ** Set tzname elements to initial values.
  238.     */
  239.     tzname[0] = tzname[1] = &s.chars[0];
  240. #ifdef USG_COMPAT
  241.     timezone = -s.ttis[0].tt_gmtoff;
  242.     daylight = 0;
  243. #endif /* USG_COMPAT */
  244.     for (i = 1; i < s.typecnt; ++i) {
  245.         register struct ttinfo *    ttisp;
  246.  
  247.         ttisp = &s.ttis[i];
  248.         if (ttisp->tt_isdst) {
  249.             tzname[1] = &s.chars[ttisp->tt_abbrind];
  250. #ifdef USG_COMPAT
  251.             daylight = 1;
  252. #endif /* USG_COMPAT */ 
  253.         } else {
  254.             tzname[0] = &s.chars[ttisp->tt_abbrind];
  255. #ifdef USG_COMPAT
  256.             timezone = -ttisp->tt_gmtoff;
  257. #endif /* USG_COMPAT */ 
  258.         }
  259.     }
  260.     return 0;
  261. }
  262.  
  263. static
  264. tzsetkernel()
  265. {
  266.     struct timeval    tv;
  267.     struct timezone    tz;
  268.     char    *_tztab();
  269.  
  270.     if (gettimeofday(&tv, &tz))
  271.         return -1;
  272.     s.timecnt = 0;        /* UNIX counts *west* of Greenwich */
  273.     s.ttis[0].tt_gmtoff = tz.tz_minuteswest * -SECS_PER_MIN;
  274.     s.ttis[0].tt_abbrind = 0;
  275.     (void)strcpy(s.chars, _tztab(tz.tz_minuteswest, 0));
  276.     tzname[0] = tzname[1] = s.chars;
  277. #ifdef USG_COMPAT
  278.     timezone = tz.tz_minuteswest * 60;
  279.     daylight = tz.tz_dsttime;
  280. #endif /* USG_COMPAT */
  281.     return 0;
  282. }
  283.  
  284. static
  285. tzsetgmt()
  286. {
  287.     s.timecnt = 0;
  288.     s.ttis[0].tt_gmtoff = 0;
  289.     s.ttis[0].tt_abbrind = 0;
  290.     (void) strcpy(s.chars, "GMT");
  291.     tzname[0] = tzname[1] = s.chars;
  292. #ifdef USG_COMPAT
  293.     timezone = 0;
  294.     daylight = 0;
  295. #endif /* USG_COMPAT */
  296. }
  297.  
  298. void
  299. tzset()
  300. {
  301.     register char *    name;
  302.  
  303.     tz_is_set = TRUE;
  304.     name = getenv("TZ");
  305.     if (!name || *name) {            /* did not request GMT */
  306.         if (name && !tzload(name))    /* requested name worked */
  307.             return;
  308.         if (!tzload((char *)0))        /* default name worked */
  309.             return;
  310.         if (!tzsetkernel())        /* kernel guess worked */
  311.             return;
  312.     }
  313.     tzsetgmt();                /* GMT is default */
  314. }
  315.  
  316. struct tm *
  317. localtime(timep)
  318. time_t *    timep;
  319. {
  320.     register struct ttinfo *    ttisp;
  321.     register struct tm *        tmp;
  322.     register int            i;
  323.     time_t                t;
  324.  
  325.     if (!tz_is_set)
  326.         (void) tzset();
  327.     t = *timep;
  328.     if (s.timecnt == 0 || t < s.ats[0]) {
  329.         i = 0;
  330.         while (s.ttis[i].tt_isdst)
  331.             if (++i >= s.timecnt) {
  332.                 i = 0;
  333.                 break;
  334.             }
  335.     } else {
  336.         for (i = 1; i < s.timecnt; ++i)
  337.             if (t < s.ats[i])
  338.                 break;
  339.         i = s.types[i - 1];
  340.     }
  341.     ttisp = &s.ttis[i];
  342.     /*
  343.     ** To get (wrong) behavior that's compatible with System V Release 2.0
  344.     ** you'd replace the statement below with
  345.     **    tmp = offtime((time_t) (t + ttisp->tt_gmtoff), 0L);
  346.     */
  347.     tmp = offtime(&t, ttisp->tt_gmtoff);
  348.     tmp->tm_isdst = ttisp->tt_isdst;
  349.     tzname[tmp->tm_isdst] = &s.chars[ttisp->tt_abbrind];
  350.     tmp->tm_zone = &s.chars[ttisp->tt_abbrind];
  351.     return tmp;
  352. }
  353.  
  354. struct tm *
  355. gmtime(clock)
  356. time_t *    clock;
  357. {
  358.     register struct tm *    tmp;
  359.  
  360.     tmp = offtime(clock, 0L);
  361.     tzname[0] = "GMT";
  362.     tmp->tm_zone = "GMT";        /* UCT ? */
  363.     return tmp;
  364. }
  365.  
  366. static int    mon_lengths[2][MONS_PER_YEAR] = {
  367.     31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
  368.     31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  369. };
  370.  
  371. static int    year_lengths[2] = {
  372.     DAYS_PER_NYEAR, DAYS_PER_LYEAR
  373. };
  374.  
  375. struct tm *
  376. offtime(clock, offset)
  377. time_t *    clock;
  378. long        offset;
  379. {
  380.     register struct tm *    tmp;
  381.     register long        days;
  382.     register long        rem;
  383.     register int        y;
  384.     register int        yleap;
  385.     register int *        ip;
  386.     static struct tm    tm;
  387.  
  388.     tmp = &tm;
  389.     days = *clock / SECS_PER_DAY;
  390.     rem = *clock % SECS_PER_DAY;
  391.     rem += offset;
  392.     while (rem < 0) {
  393.         rem += SECS_PER_DAY;
  394.         --days;
  395.     }
  396.     while (rem >= SECS_PER_DAY) {
  397.         rem -= SECS_PER_DAY;
  398.         ++days;
  399.     }
  400.     tmp->tm_hour = (int) (rem / SECS_PER_HOUR);
  401.     rem = rem % SECS_PER_HOUR;
  402.     tmp->tm_min = (int) (rem / SECS_PER_MIN);
  403.     tmp->tm_sec = (int) (rem % SECS_PER_MIN);
  404.     tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYS_PER_WEEK);
  405.     if (tmp->tm_wday < 0)
  406.         tmp->tm_wday += DAYS_PER_WEEK;
  407.     y = EPOCH_YEAR;
  408.     if (days >= 0)
  409.         for ( ; ; ) {
  410.             yleap = isleap(y);
  411.             if (days < (long) year_lengths[yleap])
  412.                 break;
  413.             ++y;
  414.             days = days - (long) year_lengths[yleap];
  415.         }
  416.     else do {
  417.         --y;
  418.         yleap = isleap(y);
  419.         days = days + (long) year_lengths[yleap];
  420.     } while (days < 0);
  421.     tmp->tm_year = y - TM_YEAR_BASE;
  422.     tmp->tm_yday = (int) days;
  423.     ip = mon_lengths[yleap];
  424.     for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
  425.         days = days - (long) ip[tmp->tm_mon];
  426.     tmp->tm_mday = (int) (days + 1);
  427.     tmp->tm_isdst = 0;
  428.     tmp->tm_zone = "";
  429.     tmp->tm_gmtoff = offset;
  430.     return tmp;
  431. }
  432. @
  433.  
  434.  
  435. 1.2
  436. log
  437. @Lint.
  438. @
  439. text
  440. @d147 1
  441. a147 1
  442.         if ((fid = open(name, 0)) == -1)
  443. @
  444.  
  445.  
  446. 1.1
  447. log
  448. @Initial revision
  449. @
  450. text
  451. @d20 4
  452. a23 3
  453. #include "sys/param.h"
  454. #include "sys/time.h"
  455. #include "tzfile.h"
  456. @
  457.